package main

import (
	"context"
	"crypto/tls"
	"crypto/x509"
	"encoding/base64"
	"fmt"
	"io/ioutil"
	"log"
	"strings"

	pb "go.etcd.io/etcd/api/v3/etcdserverpb"
	clientv3 "go.etcd.io/etcd/client/v3"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
)

var (
	KEY   = "/cube/network/lbaas/test"
	VALUE = "test"
)

var (
	CubeGatewayEndpoint  = "tjtj-ctcucm-06.vegamews.volces.com:8888"
	CubeGatewayCaCrt     = "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJuekNDQVVXZ0F3SUJBZ0lVTWp4MUdic0orM0Mva2pGNzVHU2dNQ3V5elE4d0NnWUlLb1pJemowRUF3SXcKSkRFVk1CTUdBMVVFQXd3TWRHTndjSEp2ZUhrdVkyOXRNUXN3Q1FZRFZRUUdFd0pEVGpBZ0Z3MHlOREE0TWpjdwpNelF4TlRaYUdBOHlNVEkwTURnd016QXpOREUxTmxvd0pERVZNQk1HQTFVRUF3d01kR053Y0hKdmVIa3VZMjl0Ck1Rc3dDUVlEVlFRR0V3SkRUakJaTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEEwSUFCTUZBaXc2azlSMUwKcU1JNzBiamlTa2pFNCtuenM1eXRTaHNoSDVKdW1ieHJ1NUlkMkxqUnFlNCt1WkdwaThpODdVdmh0YnZad1VTcApERkFhdFE2Y0tXYWpVekJSTUIwR0ExVWREZ1FXQkJUN0RjNGtSSTVmdFdsZjJweWtXS2RJOGlMU3FEQWZCZ05WCkhTTUVHREFXZ0JUN0RjNGtSSTVmdFdsZjJweWtXS2RJOGlMU3FEQVBCZ05WSFJNQkFmOEVCVEFEQVFIL01Bb0cKQ0NxR1NNNDlCQU1DQTBnQU1FVUNJQjJJOTJsK2tkQitBSDk0aVZ5YldGNHg3cG1YNnVHaEpQcE1XVTZvOW1uTQpBaUVBcGc3TElYNkZGRHRRbG9zMU1XTkhBNHlYejVwaUhSRVREOFBnVEcraTgrST0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo="
	CubeGatewayClientKey = "LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSU03T1ZwRVRqdFZPaTNJUjdObGp1Qi8zN1ZZbG0yU0graFBZdXVTQTlJeC9vQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFM1ZORnU0MEEyY2YyaHVMcFdTamNOMnlHNTV6Y25PTzBDbG9OUnhQanMralJma1l5eTVscApJNmNRakNWT29neExhODVGdUlaTk9hU3dCZVZTQ1c2dERRPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo="
	CubeGatewayClientCrt = "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJzVENDQVZhZ0F3SUJBZ0lVS0lZSXdyb2NpSzV4NXBBSnh5U3AyOGhaSGdnd0NnWUlLb1pJemowRUF3SXcKSkRFVk1CTUdBMVVFQXd3TWRHTndjSEp2ZUhrdVkyOXRNUXN3Q1FZRFZRUUdFd0pEVGpBZ0Z3MHlOVEF4TWpJdwpNelV5TlRsYUdBOHlNVEkwTVRJeU9UQXpOVEkxT1Zvd0pERUxNQWtHQTFVRUJoTUNRMDR4RlRBVEJnTlZCQU1NCkRIUmpjSEJ5YjNoNUxtTnZiVEJaTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEEwSUFCTjFUUmJ1TkFObkgKOW9iaTZWa28zRGRzaHVlYzNKemp0QXBhRFVjVDQ3UG8wWDVHTXN1WmFTT25FSXdsVHFJTVMydk9SYmlHVFRtawpzQVhsVWdsdXJRMmpaREJpTUFzR0ExVWREd1FFQXdJRklEQVRCZ05WSFNVRUREQUtCZ2dyQmdFRkJRY0RBakFkCkJnTlZIUTRFRmdRVWhFbDFlUm01aHNqRzJVY3EvM0NuMHBHLzdlWXdId1lEVlIwakJCZ3dGb0FVK3czT0pFU08KWDdWcFg5cWNwRmluU1BJaTBxZ3dDZ1lJS29aSXpqMEVBd0lEU1FBd1JnSWhBTDJDMHNONjJNZXd4YVIzbEdzNQpjaklHUW9lNWhUYUd3MWZzcFh0REs1L3RBaUVBOU44TTNpbzlVSjJOaFZhTTNIdUpSNlpGNU84Q2tONzJGVU9OCnJiUHRVdWM9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"
)

func getGrpcConn(ip string, port int) (*grpc.ClientConn, error) {

	caCrt, err := base64.StdEncoding.DecodeString(CubeGatewayCaCrt)
	if err != nil {
		fmt.Printf("decode cacrt failed, %s\n", err.Error())
		return nil, err
	}

	clientCrt, err := base64.StdEncoding.DecodeString(CubeGatewayClientCrt)
	if err != nil {
		fmt.Printf("decode clientcrt failed, %s\n", err.Error())
		return nil, err
	}

	clientKey, err := base64.StdEncoding.DecodeString(CubeGatewayClientKey)
	if err != nil {
		fmt.Printf("decode clientkey failed, %s\n", err.Error())
		return nil, err
	}

	clientCert, err := tls.X509KeyPair(clientCrt, clientKey)
	if err != nil {
		fmt.Printf("load ssl client cert failed, %s\n", err.Error())
		return nil, err
	}

	certPool := x509.NewCertPool()
	if !certPool.AppendCertsFromPEM(caCrt) {
		panic("AppendCertsFromPEM")
	}

	tlsConfig := &tls.Config{
		Certificates: []tls.Certificate{clientCert},
		RootCAs:      certPool,
		MinVersion:   tls.VersionTLS13,
		MaxVersion:   tls.VersionTLS13,
		ClientAuth:   tls.RequireAndVerifyClientCert,
		ServerName:   fmt.Sprintf("%s_v4_true_%d_.tcpproxy.com", strings.Replace(ip, ".", "-", -1), port),
	}

	conn, err := grpc.NewClient(CubeGatewayEndpoint, grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig)))
	if err != nil {
		fmt.Printf("new grpc client failed, %s\n", err.Error())
		return nil, err
	}
	return conn, err
}

func EtcdGrpcClientTest() *clientv3.Client {
	cert, err := tls.LoadX509KeyPair("zq_certs/server.crt", "zq_certs/server.key")
	if err != nil {
		panic(err)
	}

	// 加载CA证书
	caCrt, err := ioutil.ReadFile("zq_certs/ca.crt")
	if err != nil {
		panic(err)
	}
	// 创建CA池并添加CA证书
	caCertPool := x509.NewCertPool()
	caCertPool.AppendCertsFromPEM([]byte(caCrt))

	// 配置TLS
	tlsConfig := &tls.Config{
		Certificates: []tls.Certificate{cert},
		RootCAs:      caCertPool,
	}
	conn, err := grpc.Dial("100.65.130.169:2379", grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig)))
	if err != nil {
		fmt.Println(err.Error())
	}
	defer conn.Close()

	// 创建一个 etcd 的 KV 客户端
	client := pb.NewKVClient(conn)

	// 写入一个键值对
	putRequest := &pb.PutRequest{
		Key:   []byte(KEY),
		Value: []byte(VALUE),
	}
	putResponse, err := client.Put(context.Background(), putRequest)
	if err != nil {
		fmt.Println("写入键值对失败: ", err)
	}
	fmt.Println("写入成功，修订版本:", putResponse.Header.Revision)

	getRequest := &pb.RangeRequest{
		Key: []byte(KEY),
	}
	getResponse, err := client.Range(context.Background(), getRequest)
	if err != nil {
		log.Fatalf("读取键值对失败: %v", err)
	}
	for _, kv := range getResponse.Kvs {
		fmt.Printf("键: %s, 值: %s\n", kv.Key, kv.Value)
	}

	return nil
}

func main() {
	// EtcdGrpcClientTest()

	conn, err := getGrpcConn("100.65.130.169", 2379)
	if err != nil {
		fmt.Printf("get grpc conn failed, %s\n", err.Error())
		return
	}
	defer conn.Close()

	client := pb.NewKVClient(conn)
	// 写入一个键值对
	putRequest := &pb.PutRequest{
		Key:   []byte(KEY),
		Value: []byte(VALUE),
	}
	putResponse, err := client.Put(context.Background(), putRequest)
	if err != nil {
		fmt.Println("写入键值对失败: ", err)
	}
	fmt.Println("写入成功，修订版本:", putResponse.Header.Revision)
	getRequest := &pb.RangeRequest{
		Key: []byte(KEY),
	}
	getResponse, err := client.Range(context.Background(), getRequest)
	if err != nil {
		log.Fatalf("读取键值对失败: %v", err)
	}
	for _, kv := range getResponse.Kvs {
		fmt.Printf("键: %s, 值: %s\n", kv.Key, kv.Value)
	}

}
